﻿#pragma once

#include "include/json/json.h"
#include <ctime>
#include <string>
#include <vector>

namespace kratos {
namespace service {

/**
 * @brief 暴露容器内部工具函数给用户服务使用
 */
class Util {
public:
  virtual ~Util() {}
  // split string by any character in 'delim' and save sub-string to 'result'
  // @param src source string
  // @param delim delimeter
  // @param result sub-string result
  virtual void splitOf(const std::string &src, const std::string &delim,
                       std::vector<std::string> &result) = 0;
  // split string by 'delim' and save sub-string to 'result'
  // @param src source string
  // @param delim delimeter
  // @param result sub-string result
  virtual void split(const std::string &src, const std::string &delim,
                     std::vector<std::string> &result) = 0;
  // split string by 'delim' and save sub-string to 'result', the 'delim' will
  // keep in result
  // @param src source string
  // @param delim delimeter
  // @param result sub-string result
  virtual void splitBy(const std::string &src, char delim,
                       std::vector<std::string> &result) = 0;
  // Is 'src' end with 's'
  // @retval true
  // @retval false
  virtual bool endWith(const std::string &src, const std::string &s) = 0;
  // Is 'src' start with 's'
  // @retval true
  // @retval false
  virtual bool startWith(const std::string &src, const std::string &s) = 0;
  // erase sub-string 's' from 'src'
  // @param src source string
  // @param s target sub-string
  // @return new string
  virtual std::string remove(const std::string &src, const std::string &s) = 0;
  // erase character in 'delim' from 'src' at left side and right side
  // @param src source string
  // @param delim delimeter
  // @return new string
  virtual std::string trim(const std::string &src,
                           const std::string &delim = " ") = 0;
  // erase character in 'delim' from 'src' at left side
  // @param src source string
  // @param delim delimeter
  // @return new string
  virtual std::string ltrim(const std::string &src,
                            const std::string &delim = " ") = 0;
  // erase character in 'delim' from 'src' at right side
  // @param src source string
  // @param delim delimeter
  // @return new string
  virtual std::string rtrim(const std::string &src,
                            const std::string &delim = " ") = 0;
  // replace 'pattern' in 'src' with 'dest'
  // @param src source string
  // @param pattern the sub-string needs replacing
  // @param dest replaced sub-string
  // @return new string
  virtual std::string replace(const std::string &src,
                              const std::string &pattern,
                              const std::string &dest) = 0;
  // returns file name but not include extension
  // eg. ab/c.txt -> c
  // @param src source string
  virtual std::string get_file_name(const std::string &src) = 0;
  /**
   * Returns file name
   * eg. ab/c.txt -> c.txt
   */
  virtual std::string get_file_full_name(const std::string &src) = 0;
  /**
   * returns path of src
   *
   * e.g. a/b/c/file.ext -> a/b/c
   */
  virtual std::string get_path(const std::string &src) = 0;
  // Returns true if has the sub string
  virtual bool has_sub_string(const std::string &src,
                              const std::string &sub) = 0;

  /**
   * @brief 检测是否是一个数字，包含整数，浮点数
   */
  virtual bool isnumber(const std::string &s) = 0;
  /**
   * @brief 检测是否是IPV4地址
   */
  virtual bool is_ip_address(const std::string &s) = 0;
  /**
   * @brief 检测是否是域名
   */
  virtual bool is_domain_address(const std::string &s) = 0;
  /**
   * 检测是否是合法的主机配置, ip:port.
   */
  virtual bool is_valid_host_config(const std::string &s) = 0;
  /**
   * 检查并获取主机配置, ip:port.
   */
  virtual bool get_host_config(const std::string &s, std::string &ip,
                               int &port) = 0;
  /**
   * 将编译器产生的名字转化为人可读的名字.
   */
  virtual std::string demangle(const std::string &name) = 0;
  /**
   * 是否是日期格式: "%4d/%2d/%2d %2d:%2d:%2d".
   */
  virtual bool is_date_string_fmt1(const std::string &date_string) = 0;
  /**
   * 是否是日期格式: "%4d-%2d-%2d %2d:%2d:%2d".
   */
  virtual bool is_date_string_fmt2(const std::string &date_string) = 0;
  /**
   * 转换为人可读的字符串
   */
  virtual std::string readable_size(std::size_t size) = 0;
  /**
   * 从人可读的字符串转换为长度
   */
  virtual std::size_t
  from_readable_size_string(const std::string &size_string) = 0;
  /**
   * 解析JSON串并获取根对象
   *
   * \return true或false
   */
  virtual bool get_json_root(const std::string &json_string, Json::Value &root,
                             std::string &error) = 0;
  /**
   * 解析JSON文件并获取根对象
   *
   * \return true或false
   */
  virtual bool get_json_root_from_file(const std::string &json_file_path,
                                       Json::Value &root,
                                       std::string &error) = 0;
  // transmit from domain to IP
  // @param host domain host name
  // @return IP
  virtual std::string get_host_ip(const std::string &host) = 0;
  // returns the absobulte file path of executable binary
  // @return the absobulte file path of executable binary
  virtual std::string get_binary_path() = 0;
  // returns the executable binary file name
  virtual std::string get_binary_name() = 0;
  // Collect all files in directory
  // @param directory Directory
  // @param suffix File extension
  // @param fileNames result
  // @retval true
  // @retval false fail
  virtual bool get_file_in_directory(const std::string &directory,
                                     const std::string suffix,
                                     std::vector<std::string> &fileNames) = 0;
  // Check existence of directory
  // @param path Directory
  // @retval true
  // @retval false
  virtual bool is_path_exists(const std::string &path) = 0;
  // Remove file
  // @param filePath The file path
  // @retval true
  // @retval false
  virtual bool remove_file(const std::string &filePath) = 0;
  // Completes the path
  // @param base the base directory
  // @param sub sub-directory or file name
  // @return the joined path
  virtual std::string complete_path(const std::string &base,
                                    const std::string &sub) = 0;
  // Completes the URL path
  // @param base the base directory
  // @param sub sub-directory or file name
  // @return the joined path
  virtual std::string complete_path_url(const std::string &base,
                                        const std::string &sub) = 0;
  // Renames the file
  // @param srcFileName old file name
  // @param newFileName new file name
  // @retval true
  // @retval false
  virtual bool rename_file(const std::string &srcFileName,
                           const std::string &newFileName) = 0;
  // Returns file's suffix
  // @param fileName The file path
  virtual std::string get_file_ext(const std::string &fileName) = 0;
  // Returns the random number between a and b
  virtual std::uint32_t get_random_uint32(std::uint32_t a, std::uint32_t b) = 0;
  // 建立目录
  virtual auto make_dir(const std::string &path) -> bool = 0;
  /**
   * @brief 删除空目录
   */
  virtual auto rm_empty_dir(const std::string &path) -> bool = 0;
  /**
   * 获取进程PID.
   */
  virtual auto get_pid() -> int = 0;
  /**
   * 获取当前调用堆栈信息.
   */
  virtual auto get_current_stack_trace_info(int depth = 64) -> std::string = 0;
  /**
   * 获取文件最近一次的修改时间.
   */
  virtual auto get_last_modify_time(const std::string &path) -> std::time_t = 0;
  /**
   * @brief 获取文件指定行及上下related_line的文件内容
   * @param file_path 文件路径
   * @param line 行号
   * @param related_line 需要附带显示的上下行数
   * @param [OUT] content 文件内容
   * @return true或false
   */
  virtual auto get_file_content(const std::string &file_path, int line,
                                int related_line, std::string &content)
      -> bool = 0;
  /**
   * @brief 尝试锁定文件, 被锁定的文件在进程退出时才会被释放
   * @param file_path 文件路径
   * @return true或false
   */
  virtual auto try_lock_file(const std::string &file_path) -> bool = 0;

  /**
   * @brief 尝试解锁被try_lock_file锁定的文件
   * @param file_path 文件路径
   * @param is_remove 是否要删除
   * @return true或false
   */
  virtual auto try_unlock_file(const std::string &file_path, bool is_remove)
      -> bool = 0;

  /**
   * @brief 解锁所有被try_lock_file锁定的文件
   * @param is_remove 是否要删除
   * @return
   */
  virtual auto unlock_all_file(bool is_remove) -> void = 0;
};

} // namespace service
} // namespace kratos
